using System.ComponentModel;
using System.Linq;
using System.Collections.Generic;
using System;

using MyUtils;

using XTrace.Viewer.Properties;

namespace XTrace.Viewer.Filter
{
	public class StringSetFilter : ObservableObject, IGraphChanged
	{
		IGraphChanged _parent;

		private readonly HashSet<string> _includesSet = new HashSet<string>();
		private readonly HashSet<string> _excludesSet = new HashSet<string>();

		private bool _useIncludes;

		[DefaultValue(false)]
		public bool UseIncludes
		{
			get { return _useIncludes; }
			set
			{
				_useIncludes = value;
				if (value)
				{
					UseExcludes = false;
				}
				InvokeGraphChanged();
				OnPropertyChanged("UseIncludes");
				OnPropertyChanged("UseExcludes");
				OnPropertyChanged("All");
			}
		}

		private bool _useExcludes;

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public IGraphChanged Parent
		{
			get { return _parent; }
			set { _parent = value; }
		}

		public StringSetFilter()
		{
			
		}

		public StringSetFilter(IGraphChanged parent)
		{
			_parent = parent;
		}

		[DefaultValue(false)]
		public bool UseExcludes
		{
			get { return _useExcludes && !_useIncludes; }
			set
			{
				_useExcludes = value;
				if(value)
				{
					UseIncludes = false;
				}
				InvokeGraphChanged();
				OnPropertyChanged("UseIncludes");
				OnPropertyChanged("UseExcludes");
				OnPropertyChanged("All");
			}
		}

		protected virtual new void OnPropertyChanged(string name)
		{
			base.OnPropertyChanged(name);
			if (_parent != null)
			{
				_parent.InvokeGraphChanged(this, name);
			}
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public bool All
		{
			get { return !UseIncludes && !UseExcludes; }
			set
			{
				if (true)
				{
					UseIncludes = false;
					UseExcludes = false;
				}
				OnPropertyChanged("All");
				InvokeGraphChanged();
			}
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public bool IsActuallyAll
		{
			get
			{
				if (All)
				{
					return true;
				}
				if (UseIncludes)
				{
					return _includesSet.Count == 0;
				}
				if (UseExcludes)
				{
					return _excludesSet.Count == 0;
				}
				return false;
			}
		}

//		public IEnumerable<string> Includes
//		{
//			get { return _includesSet.ToArray(); }
//			set { _includesSet = new HashSet<string>(value); }
//		}
//
//		public IEnumerable<string> Excludes
//		{
//			get { return _excludesSet.ToArray(); }
//			set { _excludesSet = new HashSet<string>(value); }
//		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public HashSet<string> IncludesHashSet
		{
			get { return _includesSet; }
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public HashSet<string> ExcludesHashSet
		{
			get { return _excludesSet; }
		}

		public void InvokeGraphChanged(object node = null, string property = null)
		{
			if (_parent != null)
			{
				_parent.InvokeGraphChanged(node ?? this, property);
			}
			OnPropertyChanged("BriefInfo");
			OnPropertyChanged("IsActuallyAll");
			OnPropertyChanged(null);
		}

		public override string ToString()
		{
			return BriefInfo;
		}

		public string BriefInfo
		{
			get
			{
				if (IsActuallyAll)
				{
					return Resources.FilterAllActual;
				}
				if (UseIncludes)
				{
					return "+" + _includesSet.Count;
				}
				if (UseExcludes)
				{
					return "-" + _excludesSet.Count;
				}
				return "error";
			}
		}
	}
}